﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;

using Vitruvian.Logging;

namespace SpotItComponents
{
    public abstract class DeckSetupDirector
    {
        #region Private Data Members
        private static Logger logger = Logger.GetLogger(typeof(DeckSetupDirector));
        private Universe universe;
        #endregion

        #region Constructor(s)
        public DeckSetupDirector() { }
        #endregion

        #region Public Method and Properties
        /// <summary>
        /// The number of cards to create in the deck.  If this is zero at the time Setup is called, then Setup will
        /// compute the maximum number of cards that can be supported by the symbol set.
        /// </summary>
        public int NumberOfCards { get; set; }

        /// <summary>
        /// The symbol set from which the cards' symbols will be selected from
        /// </summary>
        public SymbolSet FromSymbolSet { get; set; }

        /// <summary>
        /// The deck to set up.  Note that all existing cards in the deck will be deleted before new ones are added
        /// </summary>
        public Deck TargetDeck { get; set; }

        /// <summary>
        /// Setup Method
        /// 
        /// This method will clear the target deck and then create new cards in the deck.  If NumberOfCards is 0 (or less),
        /// then it computes the maximum number of cards that the symbol set can support.
        /// </summary>
        /// <returns>If success, then the return value is an empty string; otherwise, it is an error message</returns>
        public string Setup()
        {
            string result = "";
            if (FromSymbolSet==null)
                result = "No sybmol set specified";
            else if (TargetDeck == null)
                result = "No target deck specified";
            else
            {
                universe = FindUniverse();

                if (universe==null || universe.MinimumNumberOfSymbols==0)
                    result = "Invalid number of cards";
                else
                {
                    if (!SelectSymbols(universe.MinimumNumberOfSymbols))
                        result = "There is not enough symbols in the deck";
                    else
                    {
                        ClearDeck();
                        CreateCards();
                    }
                }
            }
            return result;
        }


        #endregion

        #region Protected virtuals methods, representing steps of the setup process       
        protected abstract bool SelectSymbols(int NumberOfSymbols);

        protected virtual Universe FindUniverse()
        {
            Universe universe;

            if (NumberOfCards <= 0)
            {
                universe = FindUniverseBasedOnSymbols();
                if (universe != null)
                    NumberOfCards = universe.MaximumNumberOfCards;
            }
            else
                universe = Universe.FindUniverseBasedOnCards(NumberOfCards);

            return universe;
        }
        protected abstract Universe FindUniverseBasedOnSymbols();
        protected abstract Symbol GetSymbolByIndex(int index);

        #endregion

        #region Private Methods
        private void ClearDeck()
        {
            TargetDeck.Cards.Clear();
        }

        protected virtual void CreateCards()
        {
            logger.Debug("Creating Cards");
            List<List<int>> cardList = universe.CardCombinations();
            logger.Debug("Card list");

            for (int cardIndex = 0; cardIndex < cardList.Count && cardIndex < NumberOfCards; cardIndex++)
            {
                string tmp = "Card #"+cardIndex.ToString()+": ";
                foreach (int sIndex in cardList[cardIndex])
                    tmp += sIndex.ToString() + " ";
                logger.Debug(tmp);
            }

            for (int cardIndex=0; cardIndex<cardList.Count && cardIndex<NumberOfCards; cardIndex++)
            {
                logger.DebugFormat("Create card {0}", cardIndex);

                Card card = new Card();
                card.CreateBlankCard(universe.SymbolsPerCards);
                foreach (int symbolIndex in cardList[cardIndex])
                {
                    Symbol s = GetSymbolByIndex(symbolIndex);
                    card.AddSymbol(s);
                }

                logger.DebugFormat("Done with card");
                // card.CardImage.Save("../../../Card-" + cardIndex.ToString() + ".jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
            }
        }
        #endregion



    }
}
